package com.sun.showcase.conf.security;

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.SecurityMetadataSource;
import org.springframework.security.access.intercept.AbstractSecurityInterceptor;
import org.springframework.security.access.intercept.InterceptorStatusToken;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;


/**
 * 从数据库提取权限和资源,进行装配
 * 供spring security权限校验
 */
public class CustomerFilterSecurityInterceptor extends AbstractSecurityInterceptor implements Filter{
	
	
	private FilterInvocationSecurityMetadataSource securityMetadataSource;
	
	
	public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException {
		
		FilterInvocation filter = new FilterInvocation(request,response,chain);
		
		invoke(filter);
		
	}
	

	public void invoke(FilterInvocation filter) throws ServletException, IOException{
		
		InterceptorStatusToken token = null;
		
		try{
			
			token = super.beforeInvocation(filter);
			
		}catch(Exception e){
			
			//抛出无访问权限
			if(e instanceof AccessDeniedException){
				
				filter.getResponse().sendRedirect(filter.getHttpRequest().getContextPath()+"/error/401");   

			}
			
			return;
			
		}
		
		try{
			
			filter.getChain().doFilter(filter.getRequest(), filter.getResponse());
			
		}finally{
			
			super.afterInvocation(token, null);
		}
		
	}
	
	
	public void init(FilterConfig filterConfig)throws ServletException {
		
	}
	
	
	public void destroy() {
		
	}
	
	
	@Override
	public Class<? extends Object> getSecureObjectClass() {
		
		return FilterInvocation.class;
	}

	
	//注入资源数据定义器 
	@Override
	public SecurityMetadataSource obtainSecurityMetadataSource() {
		
		return securityMetadataSource;
	}

	public FilterInvocationSecurityMetadataSource getSecurityMetadataSource() {
		
		return securityMetadataSource;
	}

	public void setSecurityMetadataSource(FilterInvocationSecurityMetadataSource securityMetadataSource) {
		
		this.securityMetadataSource = securityMetadataSource;
	}
	
}
